﻿using JobBatDeal.Common.EsTool;
using JobBatDeal.Model;
using JobBatDeal.SqlDbHelper;
using log4net;
using Quartz;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Z.BulkOperations;
using ConvertKit = JobBatDeal.Common.ConvertKit;
using SimilarityGenerator = JobBatDeal.Common.SimilarityGenerator;

namespace JobBatDeal.Jobs
{
    public class HotelMergeJob : IJob
    {
        private readonly ILog _logger = LogManager.GetLogger(typeof(HotelMergeJob));
        FanJiaHotelEs _fanJiaHotelEsAppService = new FanJiaHotelEs();

        public void Execute(IJobExecutionContext context)
        {
            _logger.InfoFormat("===***********HotelBasicInfoUptJob 执行开始*********===");

            var dtSave = DbHelperSQL.Query($@"SELECT * FROM HotelCheckSim_ToCheck WHERE 1=0").Tables[0];
            //MergeByCity();
            //MergeByCity(Guid.Parse("F9D2DD88-B2E6-478D-9DD8-907E0B85AA1A"), dtSave).GetAwaiter().GetResult();

            //MergeByCity(Guid.Parse("B7759D12-1408-4AF4-BA58-904FD27A0C4F"), dtSave).GetAwaiter().GetResult();
            //MergeByCity(Guid.Parse("2714BC67-357E-48DB-B5C0-A11A876998F8"), dtSave).GetAwaiter().GetResult();
            //MergeByCity(Guid.Parse("93A60AD2-F006-43FC-9D88-63FC6136DF00"), dtSave).GetAwaiter().GetResult();
            MergeByCity(Guid.Parse("F9D0CAFA-DC49-4964-BA8B-C70BAF073881"), dtSave).GetAwaiter().GetResult();

            _logger.InfoFormat("===***********HotelBasicInfoUptJob 执行完成*********===");
        }

        private async Task MergeByCity(Guid cityId, DataTable dtSave)
        {
            var cityAllDt = DbHelperSQL
                   .Query($@"SELECT Id,Name,[Address],[Phone],[Longitude],[Latitude] FROM HotelBasicInfoes WHERE cityid='{cityId}' and isdeleted=0").Tables[0];

            if (cityAllDt.Rows.Count > 0)
            {
                //var hotelList = DataTableToList<FanJiaHotel>(cityAllDt);
                //await _fanJiaHotelEsAppService.CreateIndexAsync();

                var fjHotelList = new List<FanJiaHotel>();

                foreach (DataRow drHotel in cityAllDt.Rows)
                {
                    var fanJiaHotel = new FanJiaHotel
                    {
                        Id = Guid.Parse(drHotel["Id"].ToString()),
                        CityId = cityId,
                        Name = drHotel["Name"].ToString(),
                        Address = drHotel["Address"].ToString(),
                        Phone = drHotel["Phone"].ToString(),
                        Latitude = ConvertKit.ToDouble(drHotel["Latitude"]),
                        Longitude = ConvertKit.ToDouble(drHotel["Longitude"])
                    };

                    fjHotelList.Add(fanJiaHotel);
                }

                await _fanJiaHotelEsAppService.GenerateByCityAsync(cityId, fjHotelList);

                dtSave.Clear();

                _logger.Info("开始匹配>>>");

                foreach (var fanJiaHotel in fjHotelList)
                {
                    var nearHotelList = await GetFanJiaHotelListAsync(fanJiaHotel);

                    if (nearHotelList == null || nearHotelList?.Count() == 0)
                        continue;

                    foreach (var nearHotel in nearHotelList)
                    {
                        if (nearHotel.Id == fanJiaHotel.Id)
                            continue;

                        var hotelNameSimilarity = SimilarityGenerator.GetNameSimilarity(fanJiaHotel.Name, nearHotel.Name);
                        var hotelPhoneSimilarity = SimilarityGenerator.GetPhoneSimilarityRmPrex(fanJiaHotel.Phone, nearHotel.Phone);

                        var hotelCoordinateSimilarity = 0D;
                        if (fanJiaHotel.Latitude > 0 && fanJiaHotel.Longitude > 0 && nearHotel.Latitude > 0 && nearHotel.Longitude > 0)
                        {
                            hotelCoordinateSimilarity =
                                SimilarityGenerator.GetCoordinateSimilarity(fanJiaHotel.Latitude.Value, fanJiaHotel.Longitude, nearHotel.Latitude, nearHotel.Longitude);
                        }

                        //if (hotelNameSimilarity > 0.8 || hotelPhoneSimilarity == 1 || hotelCoordinateSimilarity > 0.7)
                        if ((hotelNameSimilarity > 0.84 && hotelCoordinateSimilarity > 0.9) ||
                            (hotelNameSimilarity > 0.8 && hotelPhoneSimilarity == 1) ||
                            (hotelPhoneSimilarity == 1 && hotelCoordinateSimilarity > 0.7))
                        {
                            DataRow drNew = dtSave.NewRow();
                            drNew["HotelNameSp"] = nearHotel.Name;
                            drNew["HotelNameFj"] = fanJiaHotel.Name;
                            drNew["PhoneSp"] = nearHotel.Phone;
                            drNew["PhoneFj"] = fanJiaHotel.Phone;
                            drNew["AddressSp"] = nearHotel.Address;
                            drNew["AddressFj"] = fanJiaHotel.Address;
                            drNew["HotelId"] = fanJiaHotel.Id;
                            drNew["HotelIdSp"] = nearHotel.Id;
                            drNew["NameSimilarity"] = hotelNameSimilarity;
                            drNew["PhoneSimilarity"] = hotelPhoneSimilarity;
                            drNew["CoordinateSimilarity"] = hotelCoordinateSimilarity;
                            drNew["Lng"] = fanJiaHotel.Longitude;
                            drNew["Lat"] = fanJiaHotel.Latitude;
                            drNew["LngSp"] = nearHotel.Longitude;
                            drNew["LatSp"] = nearHotel.Latitude;
                            drNew["CreationTime"] = DateTime.Now;

                            dtSave.Rows.Add(drNew);

                            _logger.Info($"符合匹配记录添加，{fanJiaHotel.Name}|{nearHotel.Name}");
                        }
                    }
                }

                if (dtSave.Rows.Count > 0)
                {
                    _logger.Info($"开始保存结果，共{dtSave.Rows.Count}条记录");

                    DbHelperSQL.ExecuteSql("TRUNCATE TABLE HotelCheckSim_ToCheck");

                    var connectionString = DbHelperSQL.connectionString;

                    try
                    {
                        using (DbConnection connection = new SqlConnection(connectionString))
                        {
                            dtSave.TableName = "HotelCheckSim_ToCheck";
                            connection.Open();
                            var bulk = new BulkOperation(connection);
                            bulk.AutoMapKeyName = "HotelId";
                            bulk.BulkInsert(dtSave);
                            //bulk.BulkUpdate(dt);
                            //bulk.BulkDelete(dt);
                            //bulk.BulkMerge(dt);
                            //bulk.BulkSaveChanges(ds);
                            //bulk.BulkSynchronize(dt);
                        }
                    }
                    catch (Exception xe)
                    {
                        _logger.Error(xe.Message, xe);
                    }
                }
            }
        }

        private async Task<List<FanJiaHotel>> GetFanJiaHotelListAsync(FanJiaHotel fanJiaHotel)
        {
            try
            {
                var maxScore = await _fanJiaHotelEsAppService.GetMaxScoreAsync(fanJiaHotel);
                if (!maxScore.HasValue)
                {
                    return null;
                }
                var total = await _fanJiaHotelEsAppService.GetTotalAsync(fanJiaHotel, maxScore.Value);
                if (!total.HasValue)
                {
                    return null;
                }
                var fanJiaHotelList = await _fanJiaHotelEsAppService.SearchAsync(fanJiaHotel, maxScore.Value, total.Value);

                return fanJiaHotelList;
            }
            catch (Exception e)
            {
                _logger.Error(e.Message, e);
                throw;
            }
        }

        /// <summary>
        /// DataTable转化为List集合
        /// </summary>
        /// <typeparam name="T">实体对象</typeparam>
        /// <param name="dt">datatable表</param>
        /// <param name="isStoreDB">是否存入数据库datetime字段，date字段没事，取出不用判断</param>
        /// <returns>返回list集合</returns>
        private List<T> DataTableToList<T>(DataTable dt, bool isStoreDB = true)
        {
            //确认参数有效 
            if (dt == null || dt.Rows.Count <= 0)
            {
                return null;
            }
            List<T> list = new List<T>();
            Type type = typeof(T);
            //List<string> listColums = new List<string>();
            PropertyInfo[] pArray = type.GetProperties(); //集合属性数组
            foreach (DataRow row in dt.Rows)
            {
                T entity = Activator.CreateInstance<T>(); //新建对象实例 
                foreach (PropertyInfo p in pArray)
                {
                    if (!dt.Columns.Contains(p.Name) || row[p.Name] == null || row[p.Name] == DBNull.Value)
                    {
                        continue;  //DataTable列中不存在集合属性或者字段内容为空则，跳出循环，进行下个循环   
                    }
                    if (isStoreDB && p.PropertyType == typeof(DateTime) && Convert.ToDateTime(row[p.Name]) < Convert.ToDateTime("1753-01-01"))
                    {
                        continue;
                    }
                    try
                    {
                        var obj = Convert.ChangeType(row[p.Name], p.PropertyType);//类型强转，将table字段类型转为集合字段类型  
                        p.SetValue(entity, obj, null);
                    }
                    catch (Exception)
                    {
                        // throw;
                    }
                }
                list.Add(entity);
            }
            return list;
        }

    }
}
